package com.eystar.ext.route;

import java.util.ArrayList;
import java.util.List;

import com.eystar.ext.kit.ClassSearcher;
import com.jfinal.config.Routes;
import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;

@SuppressWarnings("unchecked")
public class AutoBindRoutes extends Routes {

	private List<Class<? extends Controller>> excludeClasses = new ArrayList<>();

	private boolean includeAllJarsInLib;

	private List<String> includeJars = new ArrayList<>();

	protected final Log logger = Log.getLog(getClass());

	private String suffix = "Controller";

	public AutoBindRoutes addExcludeClasses(Class<? extends Controller>... clazzes) {
		if (clazzes != null) {
			for (Class<? extends Controller> clazz : clazzes) {
				excludeClasses.add(clazz);
			}
		}
		return this;
	}

	public AutoBindRoutes addExcludeClasses(List<Class<? extends Controller>> clazzes) {
		excludeClasses.addAll(clazzes);
		return this;
	}

	public AutoBindRoutes addJars(String... jars) {
		if (jars != null) {
			for (String jar : jars) {
				includeJars.add(jar);
			}
		}
		return this;
	}

	@Override
	public void config() {
		List<Class<? extends Controller>> controllerClasses = ClassSearcher.of(Controller.class).includeAllJarsInLib(includeAllJarsInLib).injars(includeJars).search();
		ControllerBind bind = null;
		for (Class<? extends Controller> controller : controllerClasses) {
			if (excludeClasses.contains(controller)) {
				continue;
			}
			bind = (ControllerBind) controller.getAnnotation(ControllerBind.class);
			if (bind == null) {
				this.add(controllerKey(controller), controller);
				logger.debug("routes.add(" + controllerKey(controller) + ", " + controller.getName() + ")");
			} else if (StrKit.isBlank(bind.viewPath())) {
				this.add(bind.controllerKey(), controller);
				logger.debug("routes.add(" + bind.controllerKey() + ", " + controller.getName() + ")");
			} else {
				this.add(bind.controllerKey(), controller, bind.viewPath());
				logger.debug("routes.add(" + bind.controllerKey() + ", " + controller + "," + bind.viewPath() + ")");
			}
		}
	}

	/**
	 * 会自动扫描没有添加ControllerBind 注释的类，但是如果该类
	 * @param controller
	 * @return
	 */
	private String controllerKey(Class<? extends Controller> controller) {
		if (!controller.getSimpleName().endsWith(suffix)) {
			throw new IllegalArgumentException(controller.getName() + " is not annotated with @ControllerBind and not end with " + suffix);
		}
		String controllerKey = "/" + StrKit.firstCharToLowerCase(controller.getSimpleName());
		controllerKey = controllerKey.substring(0, controllerKey.indexOf(suffix));
		return controllerKey;
	}

	public AutoBindRoutes includeAllJarsInLib(boolean includeAllJarsInLib) {
		this.includeAllJarsInLib = includeAllJarsInLib;
		return this;
	}

	public AutoBindRoutes suffix(String suffix) {
		this.suffix = suffix;
		return this;
	}

}
